import uniChat, { globalEmitter } from '@/lib';
import chatApi from '@/lib/api/chat';
import type { Ref } from 'vue';
import { computed, nextTick, onMounted, reactive, ref } from 'vue';

import app from '@/utils/app';
import utils from '@/utils/utils';
import { useRoute } from 'vue-router';

import { MessageType, MsgPosition } from '@/lib/types';
import dayjs from 'dayjs';
import { ElMessage } from 'element-plus';
import 'element-plus/es/components/message/style/css';
import { nanoid } from 'nanoid';

//pinia 全局存储
import type { IObject } from '@/lib/api/types';
import { useAppStore } from '@/stores';
const appStore = useAppStore();

//默认的头像
import agentAvatar from '@/assets/images/avatar/agent_avatar.webp';
import robotAvatar from '@/assets/images/avatar/robot_avatar.webp';
import visitorAvatar from '@/assets/images/avatar/visitor_avatar.webp';

import { getFileExtension } from '@/utils/fileType';
import { useDebounceFn, useThrottleFn } from '@vueuse/core';

import { ElMessageBox } from 'element-plus';
import 'element-plus/es/components/message-box/style/css';

/** @public */
export interface UseChatManagerConfig {
  onRequestOpenCameraMic: (soucreType: number, enable: boolean) => void;
}

// 视频通话状态
export enum VideoCallStatuType {
  Default = 0, // 初始状态
  Requesting = 1, // 请求中
  Waiting = 2, // 等待接听
  Talking = 3, // 视频通话中
  Closed = 4, // 会话已关闭
  Failed = 5 // 请求会话失败
}

export enum ChatMode {
  Requesting = 0, // 请求中
  AgentChatting = 1, // 坐席聊天中
  BotSession = 2, // 机器人会话
  OfflineChat = 3, // 离线但未选择发送离线
  OfflineSend = 4, // 离线选择发送离线
  Queuing = 5, // 排队中
  Blacklisted = 6, // 黑名单
  Closed = 7, // 会话已关闭
  Failed = 8 // 请求会话失败
}

type OrderMsg = {
  href?: string;
  pic: string;
  title: string;
  describe: string;
  number: string;
  price: string;
  date: string;
  type: string; // card/goods/order
};

export function useChatManager(config: UseChatManagerConfig) {
  const robotRateRef = ref(null as any);
  //pc/mobile 各自计算高度函数
  let customCountHeight: any;
  function setCustomCountHeight(f: Function) {
    customCountHeight = f;
  }
  // URL请求参数
  const urlParams = reactive({
    corpId: '', // 企业ID，对应comid参数
    workGroupName: '', // 工作组，对应wg参数
    username: '', // 用户自定义用户名
    agentName: '', // 指定客服进线客服ID
    autoVideo: '0', // 是否自动进入视频，0不自动进入视频
    alongData: '', // 随路数据，对应other参数
    fromClient: 'web',
    trackId: '', // 访问轨迹ID
    inviteId: '', // 客服邀请ID
    isVisitorInvite: '0', // 是否客服邀请会话
    history: 'false', // 是否加载历史会话消息
    skin: '', // 主题色，不配置时从服务端获取
    title: '', // 标题，不配置时从服务端获取
    titleColor: '', // 标题字体颜色，不配置时从服务端获取
    logopic: '', // logo图片
    inputHeight: '50px'
  });

  // 页面信息
  const pageData = reactive({
    transferAgentKeywords: [] as any[],
    textContent: '',
    showEmojiPannel: false, //是否展示 emoji 表情选择框
    showLeaveMessageDialog: false, //是否展示离线留言弹框
    sendLeaveMessageLoading: false, //离线留言加载中
    initError: false,
    //是否展开聊天通知
    expendNotice: false,
    clickRecord: false, //是否点击开始录音
    showRate: false, //是否展示评价弹框
    showAgentRate: false,
    chatRquesting: false, //正在请求客服
    showNoticeDialog: false, //展示公告详情弹框
    //要展示的公告详情
    noticeInfo: {
      title: '',
      content: ''
    },
    //页面标题
    chatTitle: '',
    /**
     * 服务链接信息
     */
    adList: [] as any[],
    // 信息栏配置
    infoBarConfig: {} as any,
    //是否静音
    muteFlag: false
  });

  const cardInfo = ref(); // 卡片、订单、商品信息

  //是否允许关闭聊天
  const enableCloseChat = computed(() => {
    return chatMode.value == ChatMode.AgentChatting || chatMode.value == ChatMode.BotSession;
  });

  //是否允许发送消息
  const enableSend = computed(() => {
    return (
      chatMode.value == ChatMode.AgentChatting ||
      chatMode.value == ChatMode.BotSession ||
      chatMode.value == ChatMode.OfflineSend ||
      chatMode.value == ChatMode.Queuing
    );
  });

  //是否允许发送文件/图片/录音
  const enableSendFile = computed(() => {
    return (
      chatMode.value == ChatMode.AgentChatting ||
      chatMode.value == ChatMode.OfflineSend ||
      chatMode.value == ChatMode.Queuing
    );
  });

  //是否允许主动会话评价
  const enableRate = computed(() => {
    const config: any = appStore.rateConfig;
    const canRate =
      chatMode.value == ChatMode.AgentChatting ||
      chatMode.value == ChatMode.BotSession ||
      chatMode.value == ChatMode.Closed;
    const hasChat =
      currentChatInfo.chatId && currentChatInfo.chatSessionId && currentChatInfo.workgroupName;
    return canRate && hasChat && config.id && config.surveyMethod.includes('customer');
  });

  const enableCloseRate = computed(() => {
    const config: any = appStore.rateConfig;
    const canRate =
      chatMode.value == ChatMode.AgentChatting ||
      chatMode.value == ChatMode.BotSession ||
      chatMode.value == ChatMode.Closed;
    const hasChat =
      currentChatInfo.chatId && currentChatInfo.chatSessionId && currentChatInfo.workgroupName;
    return canRate && hasChat && config.id && config.surveyMethod.includes('closed');
  });

  //是否允许视频通话
  const enableVideo = computed(() => {
    const isTalking =
      videoCallStatus.value === VideoCallStatuType.Requesting ||
      videoCallStatus.value === VideoCallStatuType.Waiting ||
      videoCallStatus.value === VideoCallStatuType.Talking;
    return (
      chatMode.value == ChatMode.AgentChatting && !isTalking && currentChatInfo.enableVideo == 1
    );
  });
  const enableEmoji = computed(() => {
    return enableSend.value && chatMode.value != ChatMode.BotSession;
  });
  //是否允许离线留言
  const enableLeaveMessage = computed(() => {
    return workGroupConfig.value.leaveMessageEnable == 1;
  });
  type stringOrNull = string | null;

  type ChatMsg = {
    id?: stringOrNull;
    messageType: stringOrNull;
    fromUser?: stringOrNull;
    toUser?: stringOrNull;
    content?: any;
    contentType?: stringOrNull;
    status?: stringOrNull;
    fromClient?: stringOrNull;
    msgId?: stringOrNull;
    workgroupName?: stringOrNull;
    sessionType?: stringOrNull;
    chatSessionId?: stringOrNull;
    chatId?: stringOrNull;
    answerType?: stringOrNull;
    data?: any;
    chatPosition?: MsgPosition; // 消息位置 左/中/右
    createDate?: stringOrNull; //创建时间
    fileMessage?: any;
    duration?: number | string;
  };

  //聊天消息列表
  const chatMsgList: Ref<ChatMsg[]> = ref([]);
  //当前会话状态
  const chatMode = ref(ChatMode.Requesting);

  const corpConfig = ref<any>({});
  const workGroupConfig = ref<any>({});

  const videoCallStatus = ref(VideoCallStatuType.Default);

  //当前会话信息
  const currentChatInfo = reactive({
    //主会话 id
    chatId: '',
    //当前会话 id
    chatSessionId: '',
    //当前工作组名称
    workgroupName: '',
    //当前会话聊天主客服
    agentname: '',
    // 会话类型
    type: 'visitor',
    // enable
    enableVideo: 0
  });

  const currentVideoInfo = reactive({
    //主会话 id
    chatId: '',
    //当前会话 id
    chatSessionId: '',
    //当前工作组名称
    workgroupName: '',
    //当前会话聊天主客服
    agentname: ''
  });

  const baseURL = ref('');

  onMounted(() => {
    init();
  });

  /**
   * 初始化配置
   */
  function init() {
    baseURL.value = app.api;
    uniChat.initParams({
      baseURL: app.api,
      socketUrl: app.socket
    });
    registerEvent();
  }

  /**
   * 检查路由，查看是否需要登录
   */
  async function checkRoute() {
    const router = useRoute();
    const {
      comid,
      wg,
      username,
      agentName,
      autoVideo,
      other,
      client,
      trackId,
      inviteId,
      isVisitorInvite,
      history,
      skin,
      title,
      titleColor,
      logopic,
      order,
      product,
      card
    } = router.query;
    if (!wg || !comid) {
      pageData.initError = true;
      ElMessage({
        message: '缺失必要参数！',
        type: 'error'
      });
      return;
    }
    // 设置全局变量
    urlParams.corpId = comid as string;
    urlParams.workGroupName = `${comid}_${wg}`;
    username && (urlParams.username = username as string);
    agentName && (urlParams.agentName = agentName as string);
    autoVideo && (urlParams.autoVideo = autoVideo as string);
    other && (urlParams.alongData = other as string);
    client && (urlParams.fromClient = client as string);
    trackId && (urlParams.trackId = trackId as string);
    inviteId && (urlParams.inviteId = inviteId as string);
    isVisitorInvite && (urlParams.isVisitorInvite = isVisitorInvite as string);
    history && (urlParams.history = history as string);
    skin && (urlParams.skin = skin as string);
    title && (urlParams.title = title as string);
    titleColor && (urlParams.titleColor = titleColor as string);
    logopic && (urlParams.logopic = logopic as string);
    uniChat.setCurrentRequestInfo(
      urlParams.workGroupName,
      urlParams.alongData,
      urlParams.fromClient
    );
    if (order && order.length > 0) {
      const encodedString = atob(order as string);
      const orderJson = decodeURIComponent(encodedString);
      const orderObject = JSON.parse(orderJson);
      console.log('=======', orderObject);
      cardInfo.value = {
        date: orderObject.date,
        href: orderObject.href,
        number: orderObject.number,
        pic: orderObject.pic,
        price: orderObject.price,
        type: MessageType.MESSAGE_ORDER
      };
    }

    if (product && product.length > 0) {
      const encodedString = atob(product as string);
      const productJson = decodeURIComponent(encodedString);
      const productObject = JSON.parse(productJson);
      cardInfo.value = {
        href: productObject.href,
        number: productObject.number,
        pic: productObject.pic,
        price: productObject.price,
        name: productObject.name,
        type: MessageType.MESSAGE_GOODS
      };
    }

    if (card && card.length > 0) {
      const encodedString = atob(card as string);
      const cardJson = decodeURIComponent(encodedString);
      const cardObject = JSON.parse(cardJson);
      cardInfo.value = {
        href: cardObject.href,
        number: cardObject.number,
        pic: cardObject.pic,
        price: cardObject.price,
        name: cardObject.name,
        type: MessageType.MESSAGE_CARD
      };
    }

    // 登录及初始化
    try {
      const userToken = appStore.userToken;
      if (!userToken) {
        await userLogin(comid as string, username as string);
      }

      //登录后
      console.log('After successful login');
      getCorpConfig();
      getWorkGroupConfig(urlParams.workGroupName);
      getNotice(urlParams.workGroupName);
      getRateConfig(urlParams.workGroupName);
      processAd(urlParams.workGroupName);
      getInfoBar(urlParams.workGroupName);
    } catch (e) {
      console.error(e);
      ElMessage({
        message: typeof e === 'string' ? e : '登录失败,请重试！',
        type: 'error'
      });
    }
  }

  /**
   * 当WebSocket连接成功后事件处理函数
   */
  function onWebSocketConnected() {
    // 加载历史记录
    if (urlParams.history === 'true') {
      recordsData.enable = true;
    }
    getHistoryMsg();
    // 检查会话并建立会话
    checkHaveChatSession();
  }

  /**
   * 注册监听事件
   */
  function registerEvent() {
    globalEmitter.on('socketStatusChange', (isConnected: any) => {
      console.log('>>>>>>> socketStatusChange: isConnected=', isConnected);
      if (isConnected) {
        onWebSocketConnected();
      }
    });
    globalEmitter.on('receiveChatMessage', (data: any) => {
      if (data.corpId && data.corpId != appStore.corpId) {
        return;
      }
      data.chatPosition = chatPosition(data.messageType, data.fromUser);
      //需要特殊处理的消息类型
      const specialProcessType = [
        MessageType.NOTIFICATION_QUEUE_LEAVE,
        MessageType.NOTIFICATION_WITHDRAW,
        MessageType.NOTIFICATION_QUEUE_ACCEPT
      ];
      if (MessageType.NOTIFICATION_VIDEO_ERROR == data.messageType) {
        data.content = '视频服务异常';
      }
      if (specialProcessType.includes(data.messageType)) {
        processOtherMsg(data);
        return;
      }

      // 需要排除不需要直接显示在聊天窗口的消息
      const ignoreMsgType = [
        MessageType.NOTIFICATION_RECEIPT,
        MessageType.NOTIFICATION_PREVIEW,
        MessageType.NOTIFICATION_VIDEO_SESSION_REENTRY,
        MessageType.NOTIFICATION_VIDEO_AGENT_JOIN_ROOM,
        MessageType.NOTIFICATION_VIDEO_PARTICIPANT_JOINED,
        MessageType.NOTIFICATION_VIDEO_PARTICIPANT_LEAVED,
        MessageType.NOTIFICATION_VIDEO_AGENT_CLOSE,
        MessageType.NOTIFICATION_VIDEO_VISITOR_CLOSE,
        MessageType.NOTIFICATION_VIDEO_AUTO_CLOSE,
        MessageType.NOTIFICATION_VIDEO_INVITE_REJECT,
        MessageType.NOTIFICATION_VIDEO_INVITE_CANCEL,
        MessageType.NOTIFICATION_VIDEO_INVITE_EXIT,
        MessageType.NOTIFICATION_VIDEO_ROOM_CHANGE_MAIN,
        MessageType.NOTIFICATION_VIDEO_OPEN_AUDIO_OR_VIDEO,
        MessageType.NOTIFICATION_QUEUE_TOP,
        MessageType.NOTIFICATION_QUEUE_TOP_CANCEL,
        MessageType.NOTIFICATION_INVITE_RATE,
        MessageType.NOTIFICATION_INVITE_RATE_CLOSE,
        MessageType.NOTIFICATION_RATE_RESULT
      ];
      if (!ignoreMsgType.includes(data.messageType)) {
        addMsgAndScollToBottom(data);
      }
      const reason = data.data?.closeReason;
      const reasomMap = {
        reject: '客服拒绝接听',
        ring_timeout: '振铃超时',
        agent_close: '客服退出视频通话',
        agent_leave: '客服退出视频通话'
      } as any;
      // 业务逻辑处理
      switch (data.messageType) {
        case MessageType.NOTIFICATION_VISITOR_CLOSE:
          //会话关闭了，取消订阅消息
          chatMode.value = ChatMode.Closed;
          data.contentType = MessageType.MESSAGE_OPERATION;
          data.content = data.content + '如需继续咨询，请点击：';
          // handlerCloseMsg();
          break;
        case MessageType.NOTIFICATION_AGENT_CLOSE:
        case MessageType.NOTIFICATION_AUTO_CLOSE:
        case MessageType.NOTIFICATION_TRANSFER_AGENT_CLOSE:
          //会话关闭了，取消订阅消息
          chatMode.value = ChatMode.Closed;
          data.content = data.content + '如需继续咨询，请点击：';
          data.contentType = MessageType.MESSAGE_OPERATION;
          // handlerCloseMsg();
          cloesRate(1);
          break;
        case MessageType.NOTIFICATION_INVITE_RATE:
        case MessageType.NOTIFICATION_INVITE_RATE_CLOSE:
          checkShowRate(data.chatSessionId, data.workgroupName, 2, data.fromUser || data.agentName);
          break;
        case MessageType.NOTIFICATION_TRANSFER_ACCEPT:
          currentChatInfo.enableVideo = data.data.newChatSession.enableVideo;
          currentChatInfo.workgroupName = data.data.newChatSession.workgroupName;
          currentChatInfo.chatSessionId = data.data.newChatSession.chatSessionId;
          currentChatInfo.agentname = data.data.newChatSession.agentName;
          currentChatInfo.type = 'visitor';
          break;
        case MessageType.NOTIFICATION_OFFLINE_MESSAGE_VISITOR_ACCEPT:
        case MessageType.NOTIFICATION_OFFLINE_ACCEPT:
        case MessageType.NOTIFICATION_SESSION:
          chatMode.value = ChatMode.AgentChatting;
          currentChatInfo.enableVideo = data.enableVideo;
          currentChatInfo.workgroupName = data.workgroupName;
          currentChatInfo.chatId = data.chatId;
          currentChatInfo.chatSessionId = data.chatSessionId;
          currentChatInfo.type = 'visitor';
          currentChatInfo.agentname = data.data?.agentName || data.fromUser;
          break;
        case MessageType.NOTIFICATION_QUEUE_TOP:
        case MessageType.NOTIFICATION_QUEUE_TOP_CANCEL:
          queueTopChange(data?.data);
          break;
        // 进入视频会话
        case MessageType.NOTIFICATION_VIDEO_SESSION_REENTRY:
        case MessageType.NOTIFICATION_VIDEO_AGENT_JOIN_ROOM:
          videoCallStatus.value = VideoCallStatuType.Talking;
          currentVideoInfo.chatSessionId = data.chatSessionId;
          currentVideoInfo.chatId = data.chatId;
          currentVideoInfo.workgroupName = data.workgroupName;
          currentVideoInfo.agentname = data.data?.videoSession.agentName || data.fromUser;
          uniChat.subscribeRoom(data.chatSessionId);
          // 打开视频窗口
          videoURL.value = data.data.roomUrl;
          videoDialogRef.value?.showDialog();
          // 删除等待消息
          reomveMsgByType(MessageType.NOTIFICATION_VIDEO_WAIT_AGENT_ANSWER);
          break;
        case MessageType.NOTIFICATION_VIDEO_PARTICIPANT_JOINED:
          if (appStore.userName !== data.data.identity) {
            addMsgAndScollToBottom(
              buildSystemMessage(`${data.data.name} 加入视频通话`, data.messageType)
            );
          }
          break;
        case MessageType.NOTIFICATION_VIDEO_PARTICIPANT_LEAVED:
          if (appStore.userName !== data.data.identity) {
            addMsgAndScollToBottom(
              buildSystemMessage(`${data.data.name} 离开视频通话`, data.messageType)
            );
          } else {
            videoCallStatus.value = VideoCallStatuType.Closed;
            videoDialogRef.value.handleClose();
          }
          break;
        case MessageType.NOTIFICATION_VIDEO_AGENT_CLOSE:
        case MessageType.NOTIFICATION_VIDEO_VISITOR_CLOSE:
        case MessageType.NOTIFICATION_VIDEO_AUTO_CLOSE:
          if (reasomMap[reason]) {
            ElMessage({ message: reasomMap[reason] + '，自动关闭视频', type: 'warning' });
          }
          videoCallStatus.value = VideoCallStatuType.Closed;
          videoDialogRef.value.handleClose();
          addMsgAndScollToBottom(buildSystemMessage('视频通话结束', data.messageType));
          break;
        case MessageType.NOTIFICATION_VIDEO_OPEN_AUDIO_OR_VIDEO:
          config.onRequestOpenCameraMic(data.data.trackSource, data.data.mute);
          break;
      }
    });
  }
  /**
   *
   * @param data 处理消息
   */
  function processOtherMsg(data: any) {
    switch (data.messageType) {
      case MessageType.NOTIFICATION_QUEUE_LEAVE:
        //队列离开 需更新当前数量
        changeQueueMsg(false);
        break;
      case MessageType.NOTIFICATION_WITHDRAW:
        //撤回消息，非自己时才需要处理
        if (data.fromUser != appStore.userName) {
          updateWithdrawMsg(data.id);
        }
        break;
      case MessageType.NOTIFICATION_QUEUE_ACCEPT:
        //队列被接受
        chatMode.value = ChatMode.AgentChatting;
        currentChatInfo.enableVideo = data.data?.enableVideo;
        currentChatInfo.workgroupName = data.workgroupName;
        currentChatInfo.chatId = data.chatId;
        currentChatInfo.chatSessionId = data.chatSessionId;
        currentChatInfo.type = 'visitor';
        currentChatInfo.agentname = data.data?.agentName || data.fromUser;
        changeQueueMsg(true);
        addMsgAndScollToBottom(data);
        break;
    }
  }

  /**
   * @param accept 是否是被接受， 接受了就移除，其他就顺序减一
   */
  function changeQueueMsg(accept: boolean) {
    const index = chatMsgList.value.findLastIndex(
      (item) => item.messageType == MessageType.NOTIFICATION_QUEUE
    );
    if (index < 0) return;
    if (accept) {
      chatMsgList.value.splice(index, 1);
    } else {
      const queueNum = chatMsgList.value[index].data;
      if (isNaN(queueNum)) {
        chatMsgList.value[index].data = 1;
      } else {
        chatMsgList.value[index].data = Math.max(Number(queueNum) - 1, 1);
      }
    }
  }

  /**
   * 置顶/取消置顶队列数改变
   * @param queueNum 当前排队数
   */
  function queueTopChange(queueNum?: Number) {
    const index = chatMsgList.value.findLastIndex(
      (item) => item.messageType == MessageType.NOTIFICATION_QUEUE
    );
    if (index < 0) return;
    if (queueNum) {
      chatMsgList.value[index].data = queueNum;
    }
  }

  /**
   * 处理关闭的会话消息
   */
  function handlerCloseMsg() {
    const msg: ChatMsg = {
      messageType: MessageType.NOTIFICATION_CUSTOM_CONTINUE_REQUEST,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      fromUser: 'systemNotifyUser',
      contentType: MessageType.MESSAGE_OPERATION,
      content: '如需继续咨询，请点击：',
      msgId: nanoid(),
      chatPosition: MsgPosition.LEFT
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 添加消息并滚动到底部
   */
  function addMsgAndScollToBottom(data: ChatMsg) {
    if (!data) return;
    chatMsgList.value.push(data);
    chatcontentToBottom();
  }

  /**
   * 更新最后一条消息的内容（流式）
   */
  // function updateLastMessageContent(content: string, msgId: string, json: any) {
  //   if (chatMsgList.value.length === 0) {
  //     console.warn('消息列表为空，无法更新最后一条消息！');
  //     return;
  //   }
  //   console.log('更新最后一条消息的内容（流式）', {
  //     ...json,
  //     answer: content
  //   });
  //   // 更新最后一条消息内容
  //   chatMsgList.value.forEach((msg) => {
  //     if (msg.msgId == msgId) {
  //       console.log({
  //         ...json,
  //         answer: content
  //       });
  //       msg.content = {
  //         ...json,
  //         answer: content
  //       };
  //     }
  //   });
  //   chatcontentToBottom();
  // }

  /**
   * 根据 MessgeType 移除消息
   */
  function reomveMsgByType(messageType: MessageType) {
    const index = chatMsgList.value.findLastIndex((item) => item.messageType == messageType);
    if (index >= 0) {
      chatMsgList.value.splice(index, 1);
    }
  }

  /**
   * 根据msgId移除消息
   */
  function reomveMsgById(msgId: string) {
    const index = chatMsgList.value.findLastIndex((item) => item.msgId == msgId);
    if (index >= 0) {
      chatMsgList.value.splice(index, 1);
    }
  }

  /**
   * 用户登录
   */
  async function userLogin(corpId: string, username: stringOrNull) {
    let visitor_name: string;
    let isNewUser = false;
    const storageName = localStorage.getItem('visitor_name');
    if (username) {
      //传入访客名称，使用传入访客名称，并保存
      visitor_name = username.startsWith('visitor_') ? username : `visitor_${username}`;
      //原来没有缓存，或者缓存名称不同
      if (!storageName || storageName !== visitor_name) {
        localStorage.setItem('visitor_type', 'user_define');
        isNewUser = true;
      }
    } else {
      const visitorType = localStorage.getItem('visitor_type');
      if (storageName && storageName.startsWith('visitor_') && visitorType == 'system') {
        //未传访客名称，原来有存，并且是系统自动生成，名称符合规则，直接使用即可
        visitor_name = storageName;
      } else {
        //未传访客名，原来未存 或 原来存用户自定义 或 传访客名称不符合规则，则重新生成
        visitor_name = `visitor_${nanoid()}`;
        localStorage.setItem('visitor_type', 'system');
        isNewUser = true;
      }
    }

    // 注册用户
    if (isNewUser) {
      const userInfo: any = await uniChat.createUser({
        corpId,
        userName: visitor_name,
        password: visitor_name,
        nickName: visitor_name.replace('visitor_', '')
      });
      // 注册成功，缓存用户名
      localStorage.setItem('visitor_name', userInfo.username);
    }

    // 登录
    const token = await uniChat.userLogin({
      corpId,
      userName: visitor_name,
      password: visitor_name
    });
    appStore.setUserInfo({
      userName: visitor_name,
      userToken: token,
      corpId: corpId
    });
  }

  /**
   * 获取企业配置
   * 包含企业配置、主题设置等信息
   */
  function getCorpConfig() {
    uniChat.getCorpConfig().then((res: any) => {
      corpConfig.value = res;
      appStore.setCorpConfig(res);
      setCustomTheme();
    });
  }

  /**
   * 获取评价配置
   */
  function getWorkGroupConfig(workGroupName: string) {
    uniChat
      .getWorkGroupConfig(workGroupName)
      .then((res: any) => {
        workGroupConfig.value = res;
        appStore.setWorkGroupConfig(res);
      })
      .catch((e) => {
        console.log(e);
        ElMessage({
          type: 'error',
          message: e.msg || '技能组信息获取失败，请检查技能组配置！'
        });
      });
  }

  /**
   * 获取评价配置
   */
  function getRateConfig(workGroupName: string) {
    uniChat
      .getRateConfig(workGroupName)
      .then((res: any) => {
        appStore.setRateConfig(res);
      })
      .catch((e) => {
        console.log(e);
        ElMessage({
          type: 'error',
          message: e.msg || '评价配置获取失败，请检查评价配置！'
        });
      });
  }

  /**
   * 请求指定坐席进线
   */
  function requestAppointAgent(workgroupName: string, agentName: string) {
    uniChat
      .appointAgent(
        workgroupName,
        agentName,
        chatMode.value == ChatMode.BotSession ? currentChatInfo.chatSessionId : ''
      )
      .then((res: any) => {
        if (res.code == 0) {
          //接入新会话
          res.data.chatPosition = MsgPosition.LEFT;
          addMsgAndScollToBottom(res.data);
          //保存当前会话 id
          saveAndSubChat(res.data);
          if (urlParams.autoVideo == '1') {
            urlParams.autoVideo = '0';
            ElMessageBox.confirm('客服邀请您进入视频通话', '', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              center: true
            })
              .then(() => {
                clickVideo();
              })
              .catch(() => {});
          }
        } else if (res.code == 10203) {
          //继续之前的会话
          addContinueMsg(res.msg);
          saveAndSubChat(res.data);
        } else if (res.code == 10204 || res.code == 10101 || res.code == 10102) {
          //10204:当前非工作时间  10101:当前无客服在线  10102:无客服，请重试
          addNoAgentMsg(res.msg, res.code);
        } else if (res.code == 11201) {
          //黑名单用户
          addBlackMsg();
        } else if (res.code == 10206) {
          //排队中
          chatMode.value = ChatMode.Queuing;
          addMsgAndScollToBottom(res.data);
        } else {
          addFailedMsg(res.msg);
        }
      })
      .catch(() => {
        addFailedMsg();
      });
  }

  /**
   * 添加继续之前会话消息
   */
  function addContinueMsg(content?: string) {
    const msg: ChatMsg = {
      messageType: MessageType.NOTIFICATION_SYS_NOTICE,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      chatPosition: MsgPosition.CENTER,
      content: content || '继续之前会话！',
      fromUser: 'systemNotifyUser',
      contentType: MessageType.MESSAGE_TEXT
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 添加无坐席消息
   */
  function addNoAgentMsg(message: string, code: number) {
    chatMode.value = ChatMode.OfflineChat;
    let content = message;
    // 非工作时间
    if (10204 == code) {
      content = workGroupConfig.value.noWorkTimeWords;
    } else {
      content = workGroupConfig.value.offlineTip;
    }
    const msg: ChatMsg = {
      messageType: MessageType.NOTIFICATION_NO_AGENT,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      chatPosition: MsgPosition.LEFT,
      content,
      fromUser: 'systemNotifyUser',
      contentType: MessageType.MESSAGE_OPERATION
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 黑名单消息
   */
  function addBlackMsg() {
    chatMode.value = ChatMode.Blacklisted;
    const msg: ChatMsg = {
      messageType: MessageType.NOTIFICATION_SYS_NOTICE,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      chatPosition: MsgPosition.LEFT,
      content: '您好，客服人员不在线。',
      fromUser: 'systemNotifyUser',
      contentType: MessageType.MESSAGE_TEXT
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 保存并订阅会话
   */
  function saveAndSubChat(data: any) {
    if (!data) return;
    currentChatInfo.chatSessionId = data.chatSessionId;
    currentChatInfo.type = 'visitor';
    currentChatInfo.chatId = data.chatId;
    currentChatInfo.enableVideo = data.data?.enableVideo;
    currentChatInfo.workgroupName = data.workgroupName || currentChatInfo.workgroupName;
    currentChatInfo.agentname = data.data?.agentName || '';
    uniChat.subcribeChatSession(data.chatSessionId);
    //状态改为客服会话聊天
    chatMode.value = ChatMode.AgentChatting;
  }

  /**
   * 请求工作组失败/或坐席忙
   */
  function addFailedMsg(errMsg?: string) {
    chatMode.value = ChatMode.Failed;
    const msg: ChatMsg = {
      messageType: MessageType.MESSAGE_REQUEST_ERROR,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      chatPosition: MsgPosition.LEFT,
      contentType: MessageType.MESSAGE_OPERATION,
      content: errMsg || '当前坐席忙！'
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 底部链接
   */
  function processAd(workGroupName: string) {
    uniChat
      .getQuickLink(workGroupName)
      .then((res: any) => {
        pageData.adList = [];
        pageData.adList.push(res);
      })
      .catch((e) => {
        console.log(e);
        ElMessage({
          type: 'error',
          message: e.msg || '页面配置信息获取失败！'
        });
      });
  }

  function getInfoBar(workGroupName: string) {
    uniChat
      .getInfoBar(workGroupName)
      .then((res: any) => {
        pageData.infoBarConfig = res;
      })
      .catch((e) => {
        console.log(e);
        ElMessage({
          type: 'error',
          message: e.msg || '页面配置信息获取失败！'
        });
      });
  }

  /**
   * 图标配置信息，没有图片设置时使用系统默认图片
   * logoEnable 未控制，默认打开
   * logoType 1 自定义  0 系统默认
   */
  const logoInfo = computed(() => {
    if (urlParams.logopic) {
      return {
        logoEnable: 0,
        logoType: 1,
        logoImg: urlParams.logopic
      };
    } else {
      return {
        logoEnable: 0,
        logoType: 0
      };
    }
  });

  const recordsData = {
    enable: false, //是否允许
    scope: 0, //0:全部，1：所选技能组
    firstFlag: true, //首次加载历史页面
    historyLoading: false //正在加载历史纪录
  };

  //聊天内容区域
  const loadMoreMsg = ref<any>(null);
  /**
   * 获取历史记录和离线消息
   */
  async function getHistoryMsg() {
    if (recordsData.historyLoading) return;
    recordsData.historyLoading = true;
    const createDate = chatMsgList.value.length > 0 ? chatMsgList.value[0].createDate : undefined;
    const element = document.getElementById('chatcontent');
    const scrollH = element?.scrollHeight || 0;
    uniChat
      .getChatRecords({
        isHistory: recordsData.enable,
        chatSessionId: currentChatInfo.chatSessionId,
        workGroupName: workGroupConfig.value.workgroupName,
        firstMessageCreateTime: createDate
      })
      .then((res: any) => {
        recordsData.historyLoading = false;
        const hasData = Array.isArray(res?.records) && res.records.length > 0;
        if (hasData) {
          const records = res.records
            .map((item: any) => {
              if (item.contentType === 'msg' && item.messageType === 'text') {
                item.contentType = 'text';
              }
              item.createDate = utils.getCurrentTime(
                item.createTimestamp,
                'yyyy-MM-dd HH:mm:ss:SSS'
              );
              item.chatPosition = chatPosition(item.messageType, item.fromUser);
              if (item.messageType == 'robot') {
                item.content = JSON.parse(item.content);
              }
              return item;
            })
            .sort((a: any, b: any) => a.id - b.id)
            .filter((item: any) => item.messageType !== MessageType.NOTIFICATION_RATE_RESULT);
          chatMsgList.value.unshift(...records);
          if (recordsData.firstFlag) {
            chatcontentToBottom();
          } else {
            nextTick(() => {
              if (element) {
                setTimeout(() => {
                  const newScrollH = element.scrollHeight;
                  loadMoreMsg.value.scrollTop = newScrollH - scrollH;
                });
              }
            });
          }
        }
        if (recordsData.firstFlag) {
          //防止设置数据时频繁请求历史接口
          setTimeout(() => {
            recordsData.firstFlag = false;
          }, 500);
        }
      })
      .catch((err) => {
        recordsData.historyLoading = false;
        recordsData.firstFlag = false;
        console.log(err);
      });
  }

  /**
   * 聊天列表滑动加载更多数据
   */
  function scrollEvent(e: any) {
    //允许展示更多聊天内容
    if (recordsData.enable) {
      const topheight = e.srcElement.scrollTop || e.target.scrollTop;
      //防止第一次请求到数据将聊天记录滚动到最底部过程中频繁的请求
      if (topheight > 0 || recordsData.historyLoading || recordsData.firstFlag) {
        return;
      }
      getHistoryMsg();
    }
  }

  /**
   * 根据渠道配置 设置自定义主题色
   */
  function setCustomTheme() {
    const root = document.documentElement;
    const corpConfig: any = appStore.corpConfig;
    let title;
    //如果获取到自定义UI配置配置
    if (corpConfig?.clientConfig) {
      const uiConfig = corpConfig?.clientConfig;
      uiConfig.themeColor && root.style.setProperty('--color-main-theme', uiConfig.themeColor);
      uiConfig.chatBackColor && root.style.setProperty('--color-chat-bg', uiConfig.chatBackColor);
      uiConfig.backColor && root.style.setProperty('--color-title-bg', uiConfig.backColor);
      uiConfig.fontColor && root.style.setProperty('--color-title-text', uiConfig.fontColor);
      uiConfig.cusBubblesColor &&
        root.style.setProperty('--color-visitor-bubble', uiConfig.cusBubblesColor);
      uiConfig.cusFontColor &&
        root.style.setProperty('--color-visitor-text', uiConfig.cusFontColor);
      uiConfig.agentBubblesColor &&
        root.style.setProperty('--color-agent-bubble', uiConfig.agentBubblesColor);
      uiConfig.agentFontColor &&
        root.style.setProperty('--color-agent-text', uiConfig.agentFontColor);
      uiConfig.bubblesFontColor &&
        root.style.setProperty('--color-system-bubble', uiConfig.bubblesColor);
      uiConfig.bubblesColor &&
        root.style.setProperty('--color-system-bubble-text', uiConfig.bubblesFontColor);
      uiConfig.systemFontColor &&
        root.style.setProperty('--color-system-text', uiConfig.systemFontColor);
      uiConfig.title && (title = uiConfig.title);
    }
    // 覆盖服务端配置主题
    if (urlParams.skin) {
      root.style.setProperty('--color-main-theme', `#${urlParams.skin}`);
      root.style.setProperty('--color-title-bg', `#${urlParams.skin}`);
    }
    title = urlParams.title || title;
    if (title) {
      pageData.chatTitle = title;
      document.title = title;
    }
    if (urlParams.logopic) {
      let $favicon = document.querySelector('link[rel="icon"]') as HTMLLinkElement;
      if ($favicon !== null) {
        $favicon.href = urlParams.logopic;
      } else {
        $favicon = document.createElement('link');
        $favicon.rel = 'icon';
        $favicon.href = urlParams.logopic;
        document.head.appendChild($favicon);
      }
    }
  }

  //公告通知集合
  const noticeList: any[] = reactive([]);
  //展示的数据
  const showNoticeList = computed(() => {
    if (noticeList.length > 1) {
      return pageData.expendNotice ? [...noticeList] : [noticeList[0]];
    }
    return [...noticeList];
  });

  /**
   * 获取公告通知
   */
  function getNotice(workGroupName: string) {
    uniChat
      .getNotice(workGroupName)
      .then((res) => {
        if (noticeList.length > 0) {
          noticeList.splice(0, noticeList.length);
        }
        if (Array.isArray(res)) {
          noticeList.push(...res);
        }
        setTimeout(() => {
          customCountHeight && customCountHeight();
        }, 10);
      })
      .catch(() => {});
  }

  /**
   * 公告展开收起
   * @param expendNotice
   */
  function changeNoticeExpendStatue() {
    pageData.expendNotice = !pageData.expendNotice;
    setTimeout(() => {
      customCountHeight && customCountHeight();
    });
  }

  /**
   * 点击展示弹框
   * @param notice 通知消息
   */
  function clickNotice(notice: any) {
    pageData.noticeInfo.title = notice.title;
    pageData.noticeInfo.content = notice.content;
    pageData.showNoticeDialog = true;
  }
  /**
   * 检查是否有会话，并建立会话
   */
  function checkHaveChatSession() {
    uniChat
      .checkExistSession(workGroupConfig.value.workgroupName)
      .then((res: any) => {
        //会话信息不存在时，检查机器人
        if (!res) {
          checkRobot();
          return;
        }

        chatMode.value = ChatMode.AgentChatting;
        currentChatInfo.enableVideo = res.enableVideo;
        currentChatInfo.workgroupName = res.workgroupName;
        currentChatInfo.chatId = res.chatId;
        currentChatInfo.chatSessionId = res.chatSessionId;
        currentChatInfo.agentname = res.toUser;
        currentChatInfo.type = res.type;
        uniChat.subcribeChatSession(res.chatSessionId);
      })
      .catch(() => {
        //不存在会话，就检查是否有机器人
        checkRobot();
      });
  }

  /**
   * 机器人是否可用
   * @param workGroup
   * @returns {*}
   */
  function isRobotAvailable() {
    const workGroup = workGroupConfig.value;
    //开启机器人  机器人优先  机器人有效
    if (workGroup) {
      //机器人
      if (workGroup.robotType == 1) {
        return (
          workGroup && workGroup.robotEnable == 1 && workGroup.robot && workGroup.robot.enable == 1
        );
      }
      //在线助手，混合模式
      else {
        return workGroup && workGroup.robotEnable == 1;
      }
    }
    return false;
  }

  /**
   * 根据机器人配置检查进入机器人会话
   * @returns
   */
  function checkRobot() {
    //暂时没有 机器人配置，先直接请求工作组
    if (isRobotAvailable() && workGroupConfig.value.robotStrategy == 0) {
      console.log('机器人优先， 请求机器人接口');
      chatMode.value = ChatMode.BotSession;
      //机器人配置获取成功，并且渠道配置了机器人，并且人机策略是是机器人优先
      uniChat
        .requestRobot(workGroupConfig.value.workgroupName)
        .then((data: any) => {
          console.log('>>>>>>> requestRobot', data);
          if (!data) return;
          currentChatInfo.chatSessionId = data.chatSessionId;
          currentChatInfo.chatId = data.chatId;
          currentChatInfo.type = 'robot';
          currentChatInfo.enableVideo = 0;
          currentChatInfo.workgroupName = data.workgroupName || currentChatInfo.workgroupName;
          currentChatInfo.agentname = data.data?.agentName || '';
          // 订阅会话
          uniChat.subcribeChatSession(data.chatSessionId);
          // 设置转人工关键词
          pageData.transferAgentKeywords = data.keywords.split(',').filter((item: any) => !!item);

          const msg = buildRobotMessage(data);
          if (!msg.content) {
            msg.content = {
              answer: workGroupConfig.value.robot.answer
            };
          } else {
            if (!msg.content.answer) {
              msg.content.answer = workGroupConfig.value.robot.answer;
            }
          }
          addMsgAndScollToBottom(msg);
        })
        .catch((err) => {
          const sendMsg = buildLocalMessage('机器人请求失败', MessageType.MESSAGE_TEXT);
          sendMsg.chatPosition = MsgPosition.CENTER;
          addMsgAndScollToBottom(sendMsg);
          console.log('>>>>>>> requestRobot', err);
        });
    } else {
      //没有机器人配置.查询渠道配置工作组供用户选择
      getChannelWorkgroup();
    }
  }
  /**
   * 查询渠道下所有工作组，只有一个的话，用户无需选择，直接请求
   */
  function getChannelWorkgroup() {
    if (workGroupConfig.value.workgroupName) {
      if (urlParams.agentName) {
        requestAppointAgent(workGroupConfig.value.workgroupName, urlParams.agentName);
      } else {
        requestWorkgroup(workGroupConfig.value.workgroupName);
      }
    } else {
      ElMessage({
        type: 'error',
        message: '技能组未获取到，请检查渠道配置！'
      });
    }
  }

  /**
   * 重新请求客服
   */
  function requestAgentAgain() {
    if (chatMode.value == ChatMode.AgentChatting || chatMode.value == ChatMode.Queuing) {
      return;
    }
    getChannelWorkgroup();
  }

  /**
   * 请求工作组会话
   */
  function requestWorkgroup(workgroupName: string) {
    if (pageData.chatRquesting) return;
    pageData.chatRquesting = true;
    currentChatInfo.workgroupName = workgroupName;
    uniChat
      .requestWorkgroup(
        workgroupName,
        chatMode.value == ChatMode.BotSession ? currentChatInfo.chatSessionId : ''
      )
      .then((res: any) => {
        pageData.chatRquesting = false;
        if (res.code == 0 && res.data) {
          //接入会话
          res.data.chatPosition = MsgPosition.LEFT;
          addMsgAndScollToBottom(res.data);
          saveAndSubChat(res.data);
        } else if (res.code == 10203 && res.data) {
          addContinueMsg(res.msg);
          saveAndSubChat(res.data);
        } else if (res.code == 10204 || res.code == 10101 || res.code == 10102) {
          //10204:当前非工作时间  10101:当前无客服在线  10102:无客服，请重试
          addNoAgentMsg(res.msg, res.code);
        } else if (res.code == 11201) {
          //黑名单用户
          addBlackMsg();
        } else if (res.code == 10206) {
          //排队中
          chatMode.value = ChatMode.Queuing;
          addMsgAndScollToBottom(res.data);
        } else {
          //请求工作组失败
          addFailedMsg(res.msg || '请求工作组失败！');
        }
      })
      .catch(() => {
        pageData.chatRquesting = true;
        addFailedMsg('请求工作组失败！');
      });
  }

  //选择表情
  function selectEmotion(item: any) {
    // 获取节点
    pageData.textContent += item.meaning;
    const $inputContent = document.getElementById('inputContent');
    if ($inputContent) {
      $inputContent.innerHTML =
        $inputContent.innerHTML + '<img class="emotion-item" src="emoji/' + item.url + '">';
      sendPreviewMessage(utils.getContentText($inputContent.innerHTML));
    }
    sendPreviewDebounce();
  }
  //表情外部点击
  function emotionClickoutside() {
    if (pageData.showEmojiPannel == true) {
      pageData.showEmojiPannel = false;
    }
  }

  function showEmojiPannel() {
    if (enableSend.value || pageData.showEmojiPannel) {
      pageData.showEmojiPannel = !pageData.showEmojiPannel;
    }
    return pageData.showEmojiPannel;
  }

  //滚动聊天记录到最底部
  const chatcontentToBottom = (duration?: number) => {
    // 获取节点
    setTimeout(() => {
      const element = document.getElementById('chatcontent');
      if (element) {
        element.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'end' });
      }
    }, duration || 600);
  };

  /**
   * 处理输入框消息内筒
   * @param event
   * @returns
   */
  function lineFeed(event?: any) {
    const windowEvent: any = window.event;
    const key = event?.keyCode || windowEvent?.keyCode;
    const $inputContent = document.getElementById('inputContent');

    // Ctrl+Enter 换行
    if (key === 13 && event.ctrlKey) {
      //在当前内容后面加上<br/><br/>
      if ($inputContent) {
        $inputContent.innerHTML = $inputContent.innerHTML + '<br/><br/>';
        utils.cursorMovesToEnd($inputContent);
      }
      return false;
    }
    // Enter 发送
    if ((key === 13 && key !== event.ctrlKey) || key === 'button_send') {
      return checkSendMessage(event);
    }
    return false;
  }

  function checkSendMessage(event?: any) {
    const $inputContent = document.getElementById('inputContent');
    if (!$inputContent) return false;
    utils.cursorMovesToEnd($inputContent);
    if (!enableSend.value) return; //如果当前状态不允许发送消息，直接返回
    //获取ID inputContent 下所有img标签
    const screenshot: any[] = [];
    const imgList = $inputContent.querySelectorAll('img');
    //获取imgList中不包含emotion-item的
    imgList.forEach((item) => {
      if (!item.classList.contains('emotion-item')) {
        screenshot.push(item);
      }
    });
    if (screenshot.length > 5) {
      ElMessage({
        message: '最多只能上传5张图片',
        type: 'error'
      });
      return;
    }

    screenshot.forEach((item) => {
      const fileId = item.id;
      uploadFile(utils.filesArr[fileId], 'image');
      $inputContent.removeChild(item);
    });

    pageData.textContent = $inputContent.innerHTML;
    if (event && event.keyCode != 'button_send') {
      event.preventDefault();
    }
    sendMessage(MessageType.MESSAGE_TEXT, pageData.textContent);
    return true;
  }

  /**
   * 粘贴事件
   */
  function pasteEvent(event: any, success?: any) {
    console.log('=====>', event, success);
    if (utils.paste_img(event, chatMode.value == ChatMode.BotSession)) {
      success && success();
    }
  }

  function sendMessage(type: string, content: any) {
    if (content.replace(/\s*/g, '') == '') {
      return;
    }
    //将br标签替换为\n
    content = content.replace(/<br>/g, '\n');
    content = content.replace(/&nbsp;/g, ' ');
    content = utils.getContentText(content);
    if (type == MessageType.MESSAGE_TEXT && utils.isLink(content)) {
      type = MessageType.MESSAGE_LINK;
    }
    if (
      chatMode.value == ChatMode.OfflineSend ||
      chatMode.value == ChatMode.Queuing ||
      chatMode.value == ChatMode.AgentChatting
    ) {
      const sendMsg = buildLocalMessage(content, type);
      const sendId = sendMsg.msgId;
      if (chatMode.value == ChatMode.AgentChatting) {
        sendMsg.chatSessionId = currentChatInfo.chatSessionId;
      }
      addMsgAndScollToBottom(sendMsg);
      sendChatMessage(sendId as string, sendMsg);
    } else if (chatMode.value == ChatMode.BotSession) {
      //发送机器人消息
      sendRobotMessage(null, content);
    }
    //清空输入框
    if (type == 'text' || type == 'link') {
      pageData.textContent = '';
      const $inputContent = document.getElementById('inputContent');
      if ($inputContent) {
        $inputContent.innerHTML = '';
      }
    }
  }

  /**
   * 发送本地消息
   * @param localMsgId  本地消息id
   * @param sendMsg  发送的消息
   */
  function sendChatMessage(localMsgId: string, sendMsg: ChatMsg) {
    uniChat
      .sendMessage(sendMsg)
      .then((res: any) => {
        updataMsgStatus(localMsgId, 'success', res);
      })
      .catch((err) => {
        ElMessage({
          message: err?.msg || '发送失败',
          type: 'error'
        });
        updataMsgStatus(localMsgId, 'failed');
      });
  }

  /**
   * 选择文件结果
   * @param event  文件选择事件
   */
  function selectFile(event: any) {
    const file = event.target.files[0];
    const fileSize = file.size;
    let type = file.type.split('/')[0];
    if (type != 'video' && type != 'image') {
      type = 'file';
    }
    //图片大于10M拦截
    if (type == 'image' && fileSize > 10 * 1024 * 1024) {
      ElMessage({
        message: '只能上传10M以内图片',
        type: 'error'
      });
      clearInput(type);
      return;
    }
    //视频及文件大小超出20M拦截
    if (fileSize > 20 * 1024 * 1024) {
      ElMessage({
        message: '只能上传20M以内文件',
        type: 'error'
      });
      clearInput(type);
      return;
    }
    const fileExt = getFileExtension(file.name);
    const notAllowFile = ['html', 'xhtml', 'shtm', 'css', 'js', 'php'];
    if (notAllowFile.includes(fileExt)) {
      ElMessage({
        message: '不支持发送该类型文件',
        type: 'error'
      });
      clearInput(type);
      return;
    }
    clearInput(type);
    uploadFile(file, type);
  }

  /**
   *
   */
  function clearInput(type: string) {
    const inputElement = document.getElementById(type + 'Input') as HTMLInputElement;
    //清空input值，防止同一文件无法触发change事件
    if (inputElement) {
      inputElement.value = '';
    }
  }

  //发送录音
  function sendVoice(recordResult: any) {
    if (recordResult.duration < 2) {
      ElMessage({
        message: '录音时间太短',
        type: 'error'
      });
      return;
    } else {
      uploadFile(recordResult.blob, MessageType.MESSAGE_VOICE);
    }
  }
  /**
   * 当前要评价的会话信息
   */
  let rateInfo: {
    chatSessionId?: string;
    workgroupName?: string;
    agentName?: string;
    rate5Type?: number;
  } = {};

  const rateDialog = ref<any>(null);

  /**
   * 点击评价
   */
  function clickRate() {
    const config: any = appStore.rateConfig;
    if (!config || !config.id || pageData.showRate) {
      return;
    }

    if (enableRate.value) {
      checkShowRate(
        currentChatInfo.chatSessionId,
        currentChatInfo.workgroupName,
        3,
        currentChatInfo.agentname,
        true
      );
    }
  }

  /**
   * 检查并展示评分
   */
  const checkShowRate = useThrottleFn(
    (
      chatSessionId: string,
      workgroupName: string,
      rate5Type: number,
      agentName?: string,
      showTip = false
    ) => {
      if (pageData.showRate) return;
      showRate(chatSessionId, workgroupName, rate5Type, agentName);
      // uniChat
      //   .isRate(chatSessionId)
      //   .then((res) => {
      //     if (res) {
      //       if (showTip) {
      //         ElMessage({
      //           message: '您已经评价过该服务！',
      //           type: 'success'
      //         });
      //       }
      //       return;
      //     } else {
      //       showRate(chatSessionId, workgroupName, rate5Type, agentName);
      //     }
      //   })
      //   .catch(() => {
      //     showRate(chatSessionId, workgroupName, rate5Type, agentName);
      //   });
    },
    1000
  );

  function showRate(
    chatSessionId: string,
    workgroupName: string,
    rate5Type: number,
    agentName?: string
  ) {
    rateInfo = {
      chatSessionId: chatSessionId,
      workgroupName: workgroupName,
      agentName: agentName,
      rate5Type: rate5Type
    };
    console.log(currentChatInfo, chatMode.value);
    // 显示评价消息
    console.log('=====', rateInfo);
    let content = '';
    if (chatMode.value == ChatMode.BotSession || currentChatInfo?.type == 'robot') {
      content = 'robot';
      // console.log(robotRateRef.value.show);
      // robotRateRef.value.show();
    } else {
      content = 'agent';
      // pageData.showRate = true;
    }

    const msg: ChatMsg = {
      messageType: MessageType.NOTIFICATION_INVITE_RATE,
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      chatPosition: MsgPosition.LEFT,
      chatSessionId: chatSessionId,
      workgroupName: workgroupName,
      content: content,
      fromUser: 'systemNotifyUser',
      contentType: MessageType.MESSAGE_TEXT
    };
    addMsgAndScollToBottom(msg);
  }

  /**
   * 提交评价信息
   * @param param
   */
  function submitRate({
    score,
    scoreDescription,
    comment,
    tags,
    chatSessionId
  }: {
    score: number;
    scoreDescription: string;
    comment: string;
    tags: string;
    chatSessionId: string;
  }) {
    const rate = {
      rate: score,
      comment,
      tags,
      rating: scoreDescription,
      chatSessionId: chatSessionId || rateInfo.chatSessionId,
      rate5Type: rateInfo.rate5Type
    };
    uniChat
      .sendRate(rate)
      .then(() => {
        pageData.showRate = false;
        if (chatMode.value != ChatMode.BotSession) {
          rateDialog.value?.ratingEnd();
        }
        ElMessage({
          message: '评价成功！',
          type: 'success'
        });
      })
      .catch((err) => {
        if (chatMode.value != ChatMode.BotSession) {
          rateDialog.value?.ratingEnd();
        }
        ElMessage({
          message: err?.msg || '评价失败,请重试！',
          type: 'error'
        });
      });
  }

  /**
   * 上传文件
   * @param file 文件
   * @param type 文件类型
   * @param reSend 重新发送
   */
  function uploadFile(file: any, type: string) {
    const fileChatMsg = buildLoaclFileMessage(file, type);
    addMsgAndScollToBottom(fileChatMsg);
    const data = {
      file,
      workgroupName: currentChatInfo.workgroupName,
      chatSessionId: currentChatInfo.chatSessionId
    };
    uploadChatFile(fileChatMsg, data);
  }

  /**
   * 重新上传并发送文件
   * @param fileChatMsg  失败的文件消息
   */
  function reSendFile(fileChatMsg: ChatMsg) {
    const file = fileChatMsg.fileMessage.loccalFile;
    const data = {
      file,
      workgroupName: currentChatInfo.workgroupName,
      chatSessionId: currentChatInfo.chatSessionId
    };
    uploadChatFile(fileChatMsg, data);
  }

  /**
   * 上传本地文件
   * @param localMsgId 本地消息id
   * @param fileData  文件数据
   */
  function uploadChatFile(fileChatMsg: ChatMsg, fileData: any) {
    const localMsgId = fileChatMsg.msgId || nanoid();
    uniChat
      .uploadFile(fileData)
      .then((res: any) => {
        reverseSearchAndModify(
          (msg: ChatMsg) => {
            return !!msg.msgId && msg.msgId == localMsgId;
          },
          (msg: ChatMsg) => {
            msg.fileMessage = res;
            msg.content = res.filePath;
            chatcontentToBottom(0);
          }
        );
        if (chatMode.value == ChatMode.AgentChatting) {
          fileChatMsg.chatSessionId = currentChatInfo.chatSessionId;
        }
        sendFileMessage(fileChatMsg, res);
      })
      .catch(() => {
        updataMsgStatus(localMsgId as string, 'failed');
      });
  }

  /**
   * 更新消息状态
   * @param msgId 消息id
   * @param status  状态
   */
  function updataMsgStatus(msgId: string, status: string, id?: string) {
    console.log('updataMsgStatus', msgId, status, id);
    reverseSearchAndModify(
      (msg: ChatMsg) => {
        return !!msg.msgId && msg.msgId == msgId;
      },
      (msg: ChatMsg) => {
        msg.status = status;
        if (id) msg.id = id;
      }
    );
  }

  /**
   * 发送文件消息
   */

  function sendFileMessage(fileChatMsg: ChatMsg, fileMessage: IObject) {
    if (
      chatMode.value == ChatMode.AgentChatting ||
      chatMode.value == ChatMode.OfflineSend ||
      chatMode.value == ChatMode.Queuing
    ) {
      if (fileMessage) {
        fileChatMsg.fileMessage = fileMessage;
        fileChatMsg.content = fileMessage.filePath;
      }
      if (chatMode.value == ChatMode.AgentChatting) {
        fileChatMsg.chatSessionId = currentChatInfo.chatSessionId;
      }
      //发送聊天消息
      sendChatMessage(fileChatMsg.msgId as string, fileChatMsg);
    }
  }

  /**
   * 重新发送消息
   * @param index 消息位置索引
   */
  function reSendMsg(index: number, msg: ChatMsg) {
    if (
      chatMode.value != ChatMode.AgentChatting &&
      chatMode.value != ChatMode.OfflineSend &&
      chatMode.value != ChatMode.Queuing
    ) {
      ElMessage({
        type: 'warning',
        message: '当前会话状态无法发送消息！'
      });
      return;
    }
    chatMsgList.value[index].status = 'sending';
    msg.status = 'sending';
    if (chatMode.value == ChatMode.AgentChatting) {
      msg.chatSessionId = currentChatInfo.chatSessionId;
    }
    if (msg.fileMessage && msg.fileMessage.loccalFile) {
      reSendFile(msg);
    } else {
      sendChatMessage(msg.msgId as string, msg);
    }
  }

  /**
   * 发送消息预览给客服
   * @param text 当前消息内容
   */
  function sendPreviewMessage(text = '') {
    uniChat.sendPreviewMessage(currentChatInfo.chatSessionId, text);
  }

  /**
   * 点击选择发送离线消息
   */
  function clickSendOffline() {
    if (chatMode.value == ChatMode.OfflineChat) {
      chatMode.value = ChatMode.OfflineSend;
      const a: ChatMsg = {
        messageType: MessageType.NOTIFICATION_SYS_NOTICE,
        createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
        chatPosition: MsgPosition.LEFT,
        contentType: MessageType.MESSAGE_TEXT,
        content: '开始发送离线消息'
      };
      chatMsgList.value.push(a);
      chatcontentToBottom();
    }
  }

  /**
   * 点击开始留言
   */
  function clickLeaveMessage() {
    if (!enableLeaveMessage.value) {
      return;
    }
    if (
      chatMode.value == ChatMode.OfflineSend ||
      chatMode.value == ChatMode.OfflineChat ||
      chatMode.value == ChatMode.Queuing
    ) {
      if (workGroupConfig.value.leaveMessageMode == 1 && workGroupConfig.value.leaveMessageUrl) {
        window.open(workGroupConfig.value.leaveMessageUrl);
      } else {
        //如果是离线的话，可以发送留言
        pageData.showLeaveMessageDialog = true;
      }
    }
  }

  /**
   * 点击发送留言
   */
  function sendLeaveMessage({ mobile, email, content }: IObject) {
    pageData.sendLeaveMessageLoading = true;
    uniChat
      .sendleaveMessage({
        mobile,
        email,
        content,
        username: appStore.userName,
        workgroupName: currentChatInfo.workgroupName
      })
      .then(() => {
        ElMessage({
          message: '留言成功！',
          type: 'success'
        });
        pageData.sendLeaveMessageLoading = false;
        pageData.showLeaveMessageDialog = false;
      })
      .catch((error) => {
        pageData.sendLeaveMessageLoading = false;
        ElMessage({
          message: error?.msg || '留言失败,请重试！',
          type: 'error'
        });
      });
  }

  /**
   * 生成基础消息
   */
  function buildBaseMessage(contentType: string, msgId?: string): ChatMsg {
    return {
      fromUser: appStore.userName,
      messageType: contentType,
      contentType,
      msgId: msgId || nanoid(),
      createDate: dayjs().format('YYYY-MM-DD HH:mm:ss'),
      workgroupName: currentChatInfo.workgroupName,
      sessionType: 'visitor',
      chatPosition: MsgPosition.RIGHT,
      toUser: currentChatInfo.agentname
    };
  }

  /**
   * 生成文本消息
   * @param message 消息内容
   * @returns
   */
  function buildLocalMessage(message: string, contentType: string): ChatMsg {
    const baseMsg = buildBaseMessage(contentType);
    baseMsg.content = message;
    return baseMsg;
  }
  function buildLocalRobotMessage(message: string): ChatMsg {
    const baseMsg = buildBaseMessage(MessageType.MESSAGE_ROBOT);
    baseMsg.content = {
      answer: message,
      answerType: 1
    };
    baseMsg.messageType = 'robot';
    return baseMsg;
  }

  /**
   * 生成系统提醒消息，显示位置 center
   * @param message 消息内容
   * @returns
   */
  function buildSystemMessage(
    message: string,
    contentType: string = MessageType.NOTIFICATION_SYS_NOTICE
  ): ChatMsg {
    const baseMsg = buildBaseMessage(contentType);
    baseMsg.chatPosition = MsgPosition.CENTER;
    baseMsg.content = message;
    return baseMsg;
  }
  function buildRobotMessage(message: string): ChatMsg {
    const baseMsg = buildBaseMessage('text');
    baseMsg.chatPosition = MsgPosition.LEFT;
    baseMsg.content = message;
    baseMsg.fromUser = 'robot';
    baseMsg.messageType = 'robot';
    return baseMsg;
  }

  /**
   * 创建文件消息
   */
  function buildLoaclFileMessage(file: File, contentType: string): ChatMsg {
    const baseMsg = buildBaseMessage(contentType);
    baseMsg.fileMessage = {
      loccalFile: file,
      fileName: file.name
    };
    return baseMsg;
  }

  /**
   * 根据消息类型 判断聊天对话框显示位置
   * @param messageType 消息类型
   */
  function chatPosition(messageType: string, fromUser?: string): MsgPosition {
    let position = MsgPosition.LEFT;
    switch (messageType) {
      case MessageType.MESSAGE_TEXT:
      case MessageType.MESSAGE_IMAGE:
      case MessageType.MESSAGE_FILE:
      case MessageType.MESSAGE_VIDEO:
      case MessageType.MESSAGE_VOICE:
      case MessageType.MESSAGE_CARD:
      case MessageType.MESSAGE_GOODS:
      case MessageType.MESSAGE_ORDER:
      case MessageType.NOTIFICATION_SESSION:
      case MessageType.NOTIFICATION_SESSION_AGENT_REMIND:
      case MessageType.NOTIFICATION_SESSION_VISITOR_REMIND:
        position = fromUser == appStore.userName ? MsgPosition.RIGHT : MsgPosition.LEFT;
        break;
      case MessageType.NOTIFICATION_NO_AGENT:
      case MessageType.NOTIFICATION_SYS_NOTICE:
      case MessageType.NOTIFICATION_OFFLINE:
      case MessageType.NOTIFICATION_NON_WORKING_TIME:
      case MessageType.NOTIFICATION_CUSTOM_CONTINUE_REQUEST:
      case MessageType.MESSAGE_ROBOT:
      case MessageType.NOTIFICATION_INVITE_RATE:
      case MessageType.NOTIFICATION_INVITE_RATE_CLOSE:
      case MessageType.NOTIFICATION_RATE_RESULT:
        position = MsgPosition.LEFT;
        break;
      case MessageType.NOTIFICATION_SESSION_REENTRY:
      case MessageType.NOTIFICATION_AGENT_CLOSE:
      case MessageType.NOTIFICATION_VISITOR_CLOSE:
      case MessageType.NOTIFICATION_WITHDRAW:
      case MessageType.NOTIFICATION_TRANSFER:
      case MessageType.NOTIFICATION_TRANSFER_ACCEPT:
      case MessageType.NOTIFICATION_INVITE:
      case MessageType.NOTIFICATION_INVITE_ACCEPT:
      case MessageType.NOTIFICATION_INVITE_REJECT:
      case MessageType.NOTIFICATION_TRANSFER_REJECT:
      case MessageType.NOTIFICATION_APPLET_OUT_COUNT:
      case MessageType.NOTIFICATION_INVITEE_EXIT:
      case MessageType.NOTIFICATION_AUTO_CLOSE:
      case MessageType.VISITOR_ONLINE_TO_VIDEO:
      case MessageType.NOTIFICATION_QUEUE:
      case MessageType.NOTIFICATION_VIDEO_ERROR:
      case MessageType.NOTIFICATION_VIDEO_INFO:
        position = MsgPosition.CENTER;
        break;
      default:
        position = fromUser == appStore.userName ? MsgPosition.RIGHT : MsgPosition.LEFT;
        break;
    }
    return position;
  }

  /**
   * 访客关闭会话
   */
  function closeChat() {
    if (enableCloseChat.value) {
      uniChat
        .closeChat(currentChatInfo.chatSessionId)
        .then(() => {
          ElMessage({
            message: '关闭会话成功！',
            type: 'success'
          });
          //访客主动发起评价
          cloesRate(3);
        })
        .catch((err) => {
          ElMessage({
            message: err?.msg || '关闭会话失败,请重试！',
            type: 'error'
          });
        });
    }
  }

  /**
   * 发送机器人消息
   * @param questionId
   * @param questionContent
   */
  async function sendRobotMessage(questionId: any, questionContent: any) {
    console.log(questionId);
    // 发送问题
    const message = buildLocalRobotMessage(questionContent);
    message.fromUser = appStore.userName;
    message.chatSessionId = currentChatInfo.chatSessionId;
    addMsgAndScollToBottom(message);
    //如果是关键字，则转人工
    if (pageData.transferAgentKeywords.indexOf(questionContent) != -1) {
      chatApi.saveRobotQuestion(currentChatInfo.chatSessionId, questionContent, '4');
      getChannelWorkgroup();
    } else {
      // 查询回答
      uniChat
        .getRobotAnswer(
          currentChatInfo.workgroupName,
          questionId,
          questionContent,
          currentChatInfo.chatSessionId
        )
        .then((res: any) => {
          addMsgAndScollToBottom(buildRobotMessage(res));
        })
        .catch((e: any) => {
          console.error(e);
          addMsgAndScollToBottom(buildSystemMessage('系统繁忙，请稍后再试。'));
        });

      // 处理流式数据
      // handleRobotMessage(params);
    }
  }

  /**
   * 处理响应流
   * @param response - Fetch API 的响应对象
   */
  // async function handleStreamResponse(response: Response, msg: any) {
  //   const reader = response.body?.getReader();
  //   const decoder = new TextDecoder(); // 用于解码流式字节为文本
  //   let done: any = false;
  //   let buffer: any = ''; // 缓存未完整的数据块
  //   let streamingText = ''; // 缓存流式内容

  //   setTimeout(async () => {
  //     while (!done) {
  //       const { value, done: streamDone } = (await reader?.read()) ?? {};
  //       done = streamDone;
  //       if (value) {
  //         // 将二进制数据解码为字符串
  //         const chunk = decoder.decode(value, { stream: true });
  //         buffer += chunk; // 拼接缓冲区，处理可能的分块问题

  //         // 逐行解析（假设每一块 JSON 数据以换行符分隔）
  //         const lines = buffer.split('\n');
  //         buffer = lines.pop(); // 保留最后一行，可能是不完整数据
  //         for (const line of lines) {
  //           // 检查数据是否以 "data:" 开头
  //           if (line.startsWith('data:')) {
  //             const jsonString = line.slice(5).trim(); // 去掉 "data:" 前缀并去除多余空格

  //             if (jsonString === 'finish') {
  //               console.log('接收到结束标志：finish');
  //               continue; // 跳过处理 "finish"
  //             }

  //             try {
  //               const json = JSON.parse(jsonString); // 解析 JSON 数据
  //               const answer = json.answer || '';
  //               streamingText += answer; // 累加内容
  //               console.log('收到 JSON 数据：', streamingText);
  //               // 实时更新最后一条消息的内容
  //               updateLastMessageContent(streamingText, msg.msgId || '', json);
  //             } catch (error) {
  //               console.error('JSON 解析错误：', error, '内容：', jsonString);
  //             }
  //           } else {
  //             console.warn('收到非数据行：', line);
  //           }
  //         }
  //       }

  //       // 处理流结束时剩余的缓冲区
  //       if (buffer) {
  //         try {
  //           if (buffer.startsWith('data:')) {
  //             const jsonString = buffer.slice(5).trim();

  //             if (jsonString === 'finish') {
  //               console.log('接收到结束标志：finish');
  //             } else {
  //               // const json = JSON.parse(jsonString);
  //               console.log('最后的 JSON 数据：', jsonString);

  //               // TODO: 在此处理最后的 JSON 数据
  //             }
  //           }
  //         } catch (error) {
  //           console.error('缓冲区 JSON 解析错误：', error, '内容：', buffer);
  //         }
  //       }
  //     }
  //   }, 1);
  // }

  // 控制和中止异步操作
  // const controller = ref<AbortController | null>(null);

  /**
   * 处理机器人消息
   *
   * @param chatParams - 机器人消息参数
   */
  // const handleRobotMessage = async (chatParams: any): Promise<void> => {
  //   try {
  //     // 添加一个初始占位消息用于流式更新
  //     const baseMsg = buildBaseMessage('text');
  //     baseMsg.chatPosition = MsgPosition.LEFT;
  //     baseMsg.fromUser = 'robot';
  //     baseMsg.messageType = 'robot';
  //     baseMsg.content = {
  //       type: 7,
  //       answerType: 1,
  //       answer: '思考中...'
  //     };
  //     addMsgAndScollToBottom(baseMsg);

  //     // 创建新的 AbortController
  //     // chatParams.workGroupName = "100214_00000110021401120241115134447993";
  //     controller.value = new AbortController();
  //     const queryParams = new URLSearchParams(chatParams);
  //     const url = `${chatApi.getBaseUrl()}/assistant/answer?${queryParams.toString()}`;
  //     const response = await window.fetch(url, {
  //       method: 'POST',
  //       headers: {
  //         'Content-Type': 'application/json',
  //         token: localStorage.getItem('uni_chat_access_token') || ''
  //       },
  //       signal: controller.value.signal
  //     });

  //     // 检查响应状态
  //     if (!response.ok) {
  //       throw new Error(`HTTP error! status: ${response.statusText}`);
  //     } else {
  //       handleStreamResponse(response, baseMsg);
  //     }
  //   } catch (error: unknown) {
  //     if (error instanceof Error && error.name !== 'AbortError') {
  //       console.error(error.message || '请求失败');
  //     }
  //   } finally {
  //     // 确保状态复原
  //     controller.value = null;
  //   }
  // };

  /**
   *
   * @param type 1：系统自动发起评价 2：坐席主动邀请评价 3:访客主动发起评价
   */
  function cloesRate(type: number) {
    if (enableCloseRate.value) {
      checkShowRate(
        currentChatInfo.chatSessionId,
        currentChatInfo.workgroupName,
        type,
        currentChatInfo.agentname
      );
    }
  }

  const enableWithDrawType = [
    MessageType.MESSAGE_TEXT,
    MessageType.MESSAGE_VOICE,
    MessageType.MESSAGE_IMAGE,
    MessageType.MESSAGE_VIDEO,
    MessageType.MESSAGE_FILE,
    MessageType.MESSAGE_ORDER,
    MessageType.MESSAGE_GOODS,
    MessageType.MESSAGE_CARD
  ];

  /**
   *
   * @param item 判断是否可以撤回
   */
  function enableWithdraw(item: any) {
    const corpConfig: any = appStore.corpConfig;
    const enable = corpConfig?.visitorWithdrawEnable == 1;
    return (
      enable &&
      item.chatPosition == MsgPosition.RIGHT &&
      withdrawFlag.value &&
      item.status != 'sending' &&
      enableWithDrawType.includes(item.contentType) &&
      item.messageType !== MessageType.NOTIFICATION_INVITE_RATE
    );
  }

  const withdrawFlag = ref(false);

  /**
   * 是否可以复制
   * @param contentType  内容类型
   */
  function canCopy(msg?: any) {
    if (msg.messageType === MessageType.NOTIFICATION_INVITE_RATE) {
      return false;
    }
    return (
      msg.contentType == MessageType.MESSAGE_TEXT ||
      msg.contentType == MessageType.MESSAGE_RICH ||
      msg.contentType == MessageType.MESSAGE_LINK ||
      msg.messageType == 'robot'
    );
  }

  //判断消息是否还能撤回
  function verifyMessageTime(data: ChatMsg) {
    const corpConfig: any = appStore.corpConfig;
    const enable = corpConfig?.visitorWithdrawEnable == 1;
    if (!enable) return false;
    const messageTime = utils.getCurrentTime(data.createDate, 'getmillisecond');
    const nowTime = utils.getCurrentTime(new Date(), 'getmillisecond');
    const limit = corpConfig?.visitorWithdrawTimeLength;
    //两分钟以内的消息
    if (nowTime - messageTime < limit * 1000 * 60) {
      withdrawFlag.value = true;
    } else {
      withdrawFlag.value = false;
    }
  }

  /**
   * 撤回消息
   */
  function withDrawMessage(id?: stringOrNull) {
    if (!id) {
      return;
    }
    uniChat
      .withDrawMessage(id)
      .then(() => {
        updateWithdrawMsg(id);
      })
      .catch((err) => {
        ElMessage({
          message: err?.msg || '撤回消息失败,请重试！',
          type: 'error'
        });
      });
  }

  /**
   * 更新撤回消息展示
   * @param id 消息 id
   */
  function updateWithdrawMsg(id: string) {
    const index = utils.findLastIndex(chatMsgList.value, (item: ChatMsg) => {
      return item.id == id;
    });
    chatMsgList.value[index].messageType = MessageType.NOTIFICATION_WITHDRAW;
    chatMsgList.value[index].chatPosition = MsgPosition.CENTER;
  }

  /**
   * 重新编辑撤回的消息
   */
  function reEditWithdraw(content?: string) {
    if (!content) {
      return;
    }
    const $inputContent = document.getElementById('inputContent');
    if ($inputContent) {
      $inputContent.innerHTML = content;
    }
  }

  /**
   * 获取消息名称
   */
  function getShowName(item: ChatMsg) {
    const isSelfMsg = isSelf(item);
    if (item.messageType == MessageType.NOTIFICATION_WITHDRAW && isSelfMsg) {
      return '你';
    }
    if (isSelfMsg || item.chatPosition == MsgPosition.RIGHT) {
      return '我';
    }
    if (item.fromUser == 'systemNotifyUser') {
      return '系统通知';
    }
    if (item.fromUser == 'robot') {
      return '智能客服';
    }
    const uiConfig = corpConfig.value.clientConfig;
    //没有配置 直接返回 fromUser
    if (!uiConfig) {
      return getAgentName(item.fromUser || '');
    }
    if (uiConfig.agentName == 2 && uiConfig.cagentName) {
      return uiConfig.cagentName;
    }
    if (uiConfig.agentName == 1 && corpConfig.value.companyName) {
      return corpConfig.value.companyName;
    }
    if (item.fromUser) {
      return getAgentName(item.fromUser);
    }
    return '系统通知';
  }
  /**
   * 获取坐席昵称或名称
   */
  function getAgentName(agentId: string) {
    const prefix = appStore.corpId + '_';
    const defaultName = agentId.startsWith(prefix) ? agentId.slice(prefix.length) : agentId;
    if (agentInfoMap.has(agentId)) {
      const info: AgentInfo = agentInfoMap.get(agentId)!;
      if (info.status == 1) {
        return defaultName;
      } else if (info.status == 2) {
        return info.realName || info.username || defaultName;
      }
    }
    getInfoByAgentId(agentId);
    return defaultName;
  }

  /**
   * 获取头像
   */
  function getAvatarUrl(item: ChatMsg) {
    if (item.fromUser == 'robot') {
      return robotAvatar;
    }
    if (isSelf(item) || item.chatPosition == MsgPosition.RIGHT) {
      return visitorAvatar;
    }
    const uiConfig = corpConfig.value.clientConfig;

    if (!uiConfig || item.fromUser == 'systemNotifyUser') {
      return robotAvatar;
    }
    //自定义头像
    if (uiConfig.agentHeaderImg == 1 && uiConfig.headerImgUrl) {
      return uiConfig.headerImgUrl;
    }
    if (uiConfig.agentHeaderImg == 0) {
      return getAgentIcon(item.fromUser as string);
    }
    return agentAvatar;
  }

  //坐席相关信息
  type AgentInfo = {
    username: string;
    realName: string;
    headUrl: string;
    status: number; // 当前状态，0 失败，需重新请求  1 请求中  2 请求成功
  };

  // 坐席信息缓存
  const agentInfoMap = new Map<string, AgentInfo>();

  function getAgentIcon(agentId: string) {
    if (!agentId) return agentAvatar;
    if (!agentId.startsWith(appStore.corpId + '_')) {
      agentId = appStore.corpId + '_' + agentId;
    }
    if (agentInfoMap.has(agentId)) {
      const info: AgentInfo = agentInfoMap.get(agentId)!;
      if (info.status == 1) {
        return agentAvatar;
      } else if (info.status == 2) {
        if (info.headUrl) {
          return info.headUrl;
        } else {
          return agentAvatar;
        }
      }
    }
    getInfoByAgentId(agentId);
    return agentAvatar;
  }

  /**
   * 根据坐席账号获取坐席头像名称信息
   * @param agentId 坐席账号
   */
  function getInfoByAgentId(agentId: string) {
    agentInfoMap.set(agentId, {
      username: '',
      realName: '',
      headUrl: '',
      status: 1
    });
    uniChat
      .getAgentInfo(agentId)
      .then((res: any) => {
        agentInfoMap.get(agentId)!.status = 2;
        if (res) {
          agentInfoMap.get(agentId)!.username = res.username;
          agentInfoMap.get(agentId)!.realName = res.nickname;
          agentInfoMap.get(agentId)!.headUrl = res.avatarUrl;
        }
      })
      .catch(() => {
        agentInfoMap.get(agentId)!.status = 0;
      });
  }

  /**
   * 是否是自己发送消息
   */
  function isSelf(item: ChatMsg) {
    return item.fromUser == appStore.userName;
  }

  /**
   * 发送商品/订单消息
   */
  function sendCardMsg(orderMsg: OrderMsg) {
    const param = {
      ...orderMsg,
      cardPic: ''
    };
    let messageType;
    if (orderMsg.type === 'card') {
      messageType = MessageType.MESSAGE_CARD;
      param.cardPic = param.pic;
      param.cardHref = param.href;
    } else if (orderMsg.type === 'goods') {
      messageType = MessageType.MESSAGE_GOODS;
    } else {
      messageType = MessageType.MESSAGE_ORDER;
    }
    const testMsg = JSON.stringify(param);
    const orderMessage = buildLocalMessage(testMsg, messageType);
    const sendId = orderMessage.msgId;
    addMsgAndScollToBottom(orderMessage);
    if (chatMode.value == ChatMode.AgentChatting) {
      orderMessage.chatSessionId = currentChatInfo.chatSessionId;
    }
    sendChatMessage(sendId as string, orderMessage);
  }

  /**
   * 发送
   */
  function sendParamCardMsg() {
    if (!cardInfo.value) {
      return;
    }
    const testMsg = JSON.stringify(cardInfo.value);
    const messageType = cardInfo.value.type;
    const orderMessage = buildLocalMessage(testMsg, messageType);
    const sendId = orderMessage.msgId;
    addMsgAndScollToBottom(orderMessage);
    if (chatMode.value == ChatMode.AgentChatting) {
      orderMessage.chatSessionId = currentChatInfo.chatSessionId;
    }
    sendChatMessage(sendId as string, orderMessage);
  }

  /**
   * 倒序查找并修改聊天数据
   * @param condition
   * @param function
   * @returns
   */
  function reverseSearchAndModify(
    condition: (item: ChatMsg) => boolean,
    modifyFn: (item: ChatMsg) => void
  ) {
    if (chatMsgList.value.length <= 0) return;

    for (let i = chatMsgList.value.length - 1; i >= 0; i--) {
      if (condition(chatMsgList.value[i])) {
        modifyFn(chatMsgList.value[i]);
        break;
      }
    }
  }

  const audioRef = ref(null);
  //当前播放的相关信息
  const playingInfo = reactive({
    //是否正在播放
    isPlaying: false,
    // 播放类型
    playingType: '', // audio/video
    //播放的消息id
    playingMessageId: '',
    //播放的音频地址
    voiceUrl: '',
    //播放的视频地址
    videoUrl: '',
    //当前音频播放进度
    audioProgress: 0,
    //总时长
    totalDuration: 0
  });

  /**
   *播放音频
   */
  function playAudio(item: ChatMsg) {
    if (item.status == 'sending') {
      ElMessage({
        message: '消息正在发送中，请稍后重试！',
        type: 'error'
      });
      return;
    }

    if (item.status == 'failed') {
      ElMessage({
        message: '消息发送失败，请重试！',
        type: 'error'
      });
      return;
    }

    if (playingInfo.isPlaying) {
      if (playingInfo.playingType == 'audio') {
        //停止当前音频播放
        stopAudio();
      }
    }
    if (
      item.id &&
      playingInfo.playingMessageId != item.id &&
      playingInfo.playingMessageId != item.msgId
    ) {
      playingInfo.isPlaying = true;
      playingInfo.voiceUrl = item.content as string;
      playingInfo.playingType = 'audio';
      playingInfo.playingMessageId = item.id;
      playingInfo.audioProgress = 0;
      playingInfo.totalDuration = item.fileMessage?.length;
      startAudio();
    }
  }

  function stopAudio() {
    const dom: any = audioRef.value;
    if (dom) {
      dom.src = '';
      dom.src = playingInfo.voiceUrl;
      dom.play();
    }
  }

  function startAudio() {
    console.log('startAudio');
    const dom: any = audioRef.value;
    if (dom) {
      dom.src = '';
      dom.src = playingInfo.voiceUrl;
      dom.play();
    }
  }

  function audioOnprogress(e: any) {
    const progress = Math.ceil(((e.target.currentTime * 1000) / playingInfo.totalDuration) * 100);
    playingInfo.audioProgress = Math.min(progress, 100);
    console.log(
      'audioOnprogress',
      e.target.currentTime,
      e.target.duration,
      playingInfo.totalDuration,
      'progress: ',
      Math.min(progress, 100)
    );
  }

  //播放完毕
  function audioOnended() {
    console.log('audioOnended');
    playingInfo.isPlaying = false;
    playingInfo.voiceUrl = '';
    playingInfo.playingType = '';
    playingInfo.playingMessageId = '';
    playingInfo.audioProgress = 0;
  }

  const videoDialogRef = ref<any>(null);
  const videoURL = ref(null);

  function clickVideo() {
    if (!enableVideo.value) {
      return;
    }

    videoCallStatus.value = VideoCallStatuType.Requesting;
    uniChat
      .videoChat({
        fromClient: 'web',
        workgroupName: workGroupConfig.value.workgroupName,
        agentName: currentChatInfo.agentname,
        chatId: currentChatInfo.chatId,
        imChatSessionId: currentChatInfo.chatSessionId
      })
      .then((res: any) => {
        console.log('请求视频成功>>>>>', res);
        videoCallStatus.value = VideoCallStatuType.Waiting;
        // TODO: 判断是恢复会话的情况不需要下面逻辑
        const waitAnswerMsg = buildLocalMessage(
          '等待客服接听中......',
          MessageType.NOTIFICATION_VIDEO_WAIT_AGENT_ANSWER
        );
        waitAnswerMsg.chatPosition = MsgPosition.CENTER;
        addMsgAndScollToBottom(waitAnswerMsg);
        currentVideoInfo.chatSessionId = res.chatSessionId;
        currentVideoInfo.chatId = res.chatId;
        currentVideoInfo.workgroupName = res.workgroupName || currentChatInfo.workgroupName;
        currentVideoInfo.agentname = res.agentName || '';
        uniChat.subscribeRoom(res.chatSessionId);

        // todo
        videoURL.value = res.videoUrl;
        videoDialogRef.value?.showDialog();
      })
      .catch((err) => {
        console.log('请求视频失败>>>>>', err);
        videoCallStatus.value = VideoCallStatuType.Failed;
        if (err.code === 10101) {
          // 删除呼叫等待消息
          reomveMsgByType(MessageType.NOTIFICATION_VIDEO_WAIT_AGENT_ANSWER);
        }
        // 发送呼叫失败消息
        addMsgAndScollToBottom(
          buildSystemMessage(
            `视频呼叫失败，原因：${err.msg}`,
            MessageType.NOTIFICATION_VIDEO_CALL_FAIL
          )
        );
      });
  }

  /**
   * 发送消息预知
   */
  const sendPreviewDebounce = useDebounceFn(() => {
    const $inputContent = document.getElementById('inputContent');
    const text = utils.getContentText($inputContent?.innerHTML);
    sendPreviewMessage(text);
  }, 3000);

  /**
   * 复制内容
   */
  function copy(e: any, content?: any) {
    if (!content) {
      return;
    }
    console.log(e, content);
    if (typeof content == 'object') {
      content = content.answer;
      if (content.subQuestion && content.subQuestion.length) {
        content +=
          '\n ' +
          content.subQuestion
            ?.map((item: any, index: any) => `${index + 1}. ${item.question}`)
            .join('\n');
      }
    }
    utils.copyToClipboard(content, e, ElMessage, '复制成功', '复制失败');
  }

  //获取字符串内容
  const getGoodsContent = (data: any, contentType: any) => {
    //将data字符串转为对象
    const contentData = JSON.parse(data);
    console.log('=======', contentData);
    return contentData[contentType];
    // return contentType != 'pic'
    //   ? contentData[contentType]
    //   : `${imagePrefix.value}${decodeURIComponent(contentData[contentType])}`;
  };

  /**
   * 是否静音
   */
  function toggleMute(isMute: boolean) {
    pageData.muteFlag = isMute;
    localStorage.setItem('isMute', `${isMute}`);
    uniChat.toggleMute(isMute);
  }

  const imagePrefix = computed(() => {
    return `${baseURL.value}/sys/oss/download?token=${appStore.userToken}&url=`;
  });

  //  获取排队消息配置 TODO: 需要后端修改
  function getQueueMsg(data: any) {
    const corpConfig: any = appStore.corpConfig;
    if (corpConfig?.queueChineseTip) {
      return corpConfig?.queueChineseTip.replace('{0}', isNaN(data) ? '1' : data);
    }
    return `前面还有${isNaN(data) ? '1' : data}人，请您耐心等待。`;
  }

  function msgTimeDesc(date: any) {
    const time = dayjs(date);
    if (time.isSame(dayjs(), 'day')) {
      return dayjs(date).format('HH:mm');
    }
    const yestorday = dayjs().subtract(1, 'day');
    if (time.isSame(yestorday, 'day')) {
      return '昨天' + dayjs(date).format('HH:mm');
    }
    if (time.isSame(dayjs(), 'year')) {
      return dayjs(date).format('MM-DD HH:mm:ss');
    }
    return dayjs(date).format('YYYY-MM-DD HH:mm:ss');
  }

  return {
    chatMode,
    pageData,
    chatMsgList,
    noticeList,
    showNoticeList,
    workGroupConfig,
    enableCloseChat,
    enableSend,
    enableRate,
    enableSendFile,
    enableVideo,
    enableEmoji,
    rateDialog,
    enableLeaveMessage,
    loadMoreMsg,
    audioRef,
    playingInfo,
    logoInfo,
    checkRoute,
    selectEmotion,
    lineFeed,
    selectFile,
    clickSendOffline,
    clickLeaveMessage,
    sendLeaveMessage,
    chatPosition,
    getAvatarUrl,
    emotionClickoutside,
    closeChat,
    sendVoice,
    sendPreviewMessage,
    clickRate,
    checkShowRate,
    submitRate,
    requestAgentAgain,
    withDrawMessage,
    reEditWithdraw,
    getShowName,
    isSelf,
    enableWithdraw,
    canCopy,
    verifyMessageTime,
    scrollEvent,
    sendCardMsg,
    reSendMsg,
    audioOnended,
    audioOnprogress,
    playAudio,
    showEmojiPannel,
    changeNoticeExpendStatue,
    clickNotice,
    currentChatInfo,
    videoDialogRef,
    videoURL,
    videoCallStatus,
    clickVideo,
    sendPreviewDebounce,
    copy,
    getGoodsContent,
    chatcontentToBottom,
    checkSendMessage,
    setCustomCountHeight,
    toggleMute,
    reomveMsgById,
    baseURL,
    getQueueMsg,
    pasteEvent,
    sendRobotMessage,
    robotRateRef,
    msgTimeDesc,
    cardInfo,
    sendParamCardMsg  };
}
